Conversation
Co-authored-by: Franco Zalamena <franco.zalamena@iterable.com> Co-authored-by: “Akshay <“ayyanchira.akshay@gmail.com”>
iterableapi/src/main/java/com/iterable/iterableapi/IterableTaskRunner.java
Dismissed
Show dismissed
Hide dismissed
joaodordio
left a comment
There was a problem hiding this comment.
Apart from the reset() comment all looks good to me.
Claude came up with this warning which I thought was worth mentioning. Not tied to this branch but worth noting.
IterableResponseusesMap.of()which crashes on API 21-29.
Map.of()is a Java 9 API, available on Android only from API 30+. NocoreLibraryDesugaringis configured inbuild.gradle. WithminSdkVersion 21, this will throwNoSuchMethodErrorat runtime on Android 5–10 devices whensetEmail/setUserIdcompletes login.
Marking as CR so we can better understand the risk of it!
iterableapi/src/main/java/com/iterable/iterableapi/IterableAuthManager.java
Show resolved
Hide resolved
sumeruchat
left a comment
There was a problem hiding this comment.
#: 1
Bug: Callbacks dropped on retry
Summary: onTaskCompleted unconditionally removes callbacks from the maps on
RETRY. When the task eventually succeeds, callbacks are gone. Also fires
the
failure callback prematurely on 401 before retry.
────────────────────────────────────────
#: 4
Bug: Negative exponent in getNextRetryInterval
Summary: In the primary retry path, retryCount is incremented to 1 before
getNextRetryInterval is called, so it's fine. But in edge paths like
queueExpirationRefresh's catch block or checkAndHandleAuthRefresh,
retryCount can still be 0, giving exponent -1 and halving the interval.
────────────────────────────────────────
#: 5
Bug: Thread-unsafe authTokenReadyListeners
Summary: Plain ArrayList with no synchronization, accessed from multiple
threads. The snapshot copy in notifyAuthTokenReadyListeners doesn't protect
against concurrent modification during copy construction.
#6
2. setAuthState has a TOCTOU race (IterableAuthManager.java:109-114). The
read of this.authState and subsequent write are not atomic — two threads
could both read INVALID, both transition, and both fire notifications.
Consider making setAuthState synchronized.
#: 7
Bug: updateFromRemoteConfig dead code
Summary: Never called from production code. The remote config parsing only
reads KEY_OFFLINE_MODE and KEY_AUTO_RETRY, never endpoint classification.
The method exists and is tested in isolation but never wired up.
What is the solution here? there can only be 1 callback at a time, if multiple calls fail we would override them. Also if there is a 401 there is a failure, independently if it retries or not. For example a tracking should not have a callback waiting for it for something to happen, if it tracked it does not really matter when |
This is the behaviour we always had, i think it is intended, we can cut a ticket for a fix if you think it is necessary |
This should not really happen anywhere since we only have 1 call place, but i can make the fix as it is a simple one |
This is intentional, i can rename the function but it is just a placeholder if we get this list to be dynamic at some point |
The duplicate notification scenario requires two threads to both read INVALID
These happen sequentially — you get a token first, then make a request, then The only realistic "race" would be two simultaneous handleAuthTokenSuccess Worst case if it did happen: onAuthTokenReady() fires twice, which calls |
✏️ Description
Following a successful bugbash, we now have to merge the Auto retry into master.
processing (SDK-342). When a queued task gets a 401 JWT error and autoRetry is
enabled via remote config, the task is retained in the DB and processing
pauses until a valid token is obtained via an AuthTokenReadyListener callback.
disableDevice, mergeUser) continue processing during an auth pause while
JWT-required tasks wait.
coordinate pause/resume between IterableRequestTask, IterableTaskRunner, and
the auth refresh flow.